﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using XPressify.Data;
using XPressify.Data.Helpers;
using XPressify.Helpers;
using XPressify.Models;

namespace XPressify.Controllers
{
    public class StatusController : SubjectController
    {
        [Authorize]
        public ActionResult StatusOwnerList()
        {
            var user = CurrentUser;
            var allPosts =
                Repository.AsQueryable<Post>().Where(
                    pst =>
                    pst.BaseObject.Type == ObjectType.Status && pst.PostType == PostType.Post &&
                    pst.CommentType != CommentType.PostWithoutComments &&
                    pst.BaseSubject.Id == user.Id && pst.BaseObject.BaseSubject.Id == user.Id).OrderByDescending(
                        st => st.Created);
            var dictionary = new Dictionary<Post, List<Post>>();
            foreach (var post in allPosts)
            {
                var allComments = Repository.GetAllComments(post);
                dictionary.Add(post, allComments.ToList());
            }
            var model = new StatusListModel
                            {
                                Posts = dictionary,
                                CurrentUserId = user.Id,
                                ViewerProfilePicturePath = Repository.GetProfilePicturePath(user.Id),
                                IsAjaxRequest = Request.IsAjaxRequest()
                            };
            return View("StatusList", model);
        }


        [Authorize]
        public ActionResult StatusViewerList(Guid id)
        {
            var user = Repository.AsQueryable<User>().SingleOrDefault(usr => usr.Id == id);
            var currentUser = CurrentUser;
            if(user.Id == currentUser.Id)
            {
                return RedirectToAction("StatusOwnerList", "Status");
            }
            var dictionary = new Dictionary<Post, List<Post>>();

            var areFriendsOfFriends = Repository.GetFriendsOfFriendsOf(currentUser.Id).Any(fr => fr.Id == user.Id); // try to find if current user is friend of friend of user
            var areFriends = Repository.GetFriendsOf(currentUser.Id).Any(fr => fr.Id == user.Id); // try to find if current user is friend of user

            var allPosts =
                Repository.AsQueryable<Post>().Where(
                    pst =>
                    pst.BaseObject.Type == ObjectType.Status && pst.PostType == PostType.Post &&
                    pst.CommentType == CommentType.PostWithoutComments &&
                    pst.BaseSubject.Id == user.Id && pst.BaseObject.BaseSubject.Id == user.Id).OrderByDescending(
                        st => st.Created);

            foreach (var post in allPosts)
            {
                //we put them in list only if post privacy type match the relationship with
                if(post.BaseObject.PrivacyType == ObjectPrivacy.Everyone || 
                    (post.BaseObject.PrivacyType == ObjectPrivacy.FriendsOnly && areFriends == true) ||
                    (post.BaseObject.PrivacyType == ObjectPrivacy.FriendsOfFriends && (areFriendsOfFriends == true || areFriends == true)))
                {
                    var allComments = Repository.GetAllComments(post);
                    dictionary.Add(post, allComments.ToList()); // put them in dictionary list
                }
                
            }
            var model = new StatusListModel
            {
                Posts = dictionary,
                CurrentUserId = user.Id,
                ViewerProfilePicturePath = Repository.GetProfilePicturePath(currentUser.Id),
                IsAjaxRequest = Request.IsAjaxRequest()
            };
            return View("StatusList", model);
        }


        [Authorize]
        public ActionResult StatusCreate(Guid profileId)
        {
            var currentUser = CurrentUser;
            var text = currentUser.Id == profileId ? "Whats on your mind?" : "Write something...";
            short subjectType = -1;
            var subjectUser = Repository.AsQueryable<User>().SingleOrDefault(us => us.Id == profileId);
            if(subjectUser != null)
            {
                subjectType = SubjectType.User;
            }
            else
            {
                var subjectEvent = Repository.AsQueryable<Event>().SingleOrDefault(ev => ev.Id == profileId);
                if(subjectEvent != null)
                {
                    subjectType = SubjectType.Event;
                }
                else
                {
                    var subjectGroup = Repository.AsQueryable<Group>().SingleOrDefault(gr => gr.Id == profileId);
                    if (subjectGroup != null)
                    {
                        subjectType = SubjectType.Group;
                    }
                    else
                    {
                        var subjectPage = Repository.AsQueryable<Page>().SingleOrDefault(pg => pg.Id == profileId);
                        if (subjectPage != null)
                        {
                            subjectType = SubjectType.Page;
                        }
                    }
                }
            }
            var model = new StatusCreateModel
            {
                Content = text,
                UserPostedOnId = profileId,
                BaseSubjectType = subjectType
            };
            return View(model);
        }

        //
        // GET: /Status/Create
        [Authorize]
        [HttpPost]
        public ActionResult StatusCreate(Guid profileId, StatusCreateModel model)
        {
            var currentUser = CurrentUser;
            var postedOnUser = Repository.AsQueryable<User>().SingleOrDefault(u => u.Id == model.UserPostedOnId);
            
            //create new status object and post object deppending on baseSubject type and return in Dictionary<Status,Post> only one element
            var statusAndPost = GetStatusAndPost(model);
            var newStatus = statusAndPost.Keys.First();
            var newPost = statusAndPost.Values.First();

            string profilePicturePath = Repository.GetProfilePicturePath(currentUser.Id);

            var picturePath = profilePicturePath;
            var subjectId = currentUser.Id;
            var subjectFullname = currentUser.FullName;
            var isAdminPage = "false";

            //check if its page and its admin if so then post will show that page posted something on wall
            if (model.BaseSubjectType == SubjectType.Page)
            {
                var page = Repository.AsQueryable<Page>().SingleOrDefault(pg => pg.Id == model.UserPostedOnId);
                var isAdmin =
                    Repository.AsQueryable<Relationship>().Any(
                        rel =>
                        rel.BaseSubject.Id == currentUser.Id && rel.RelationType == RelationshipType.AdministratorOf);
                if (isAdmin)
                {
                    subjectId = page.Id;
                    subjectFullname = page.FullName;
                    isAdminPage = "true";

                    //default cover picture path
                    var album = Repository.AsQueryable<Album>().SingleOrDefault(al => al.BaseSubject.Id == page.Id);
                    picturePath = "/Media/" + model.UserPostedOnId + "/" + album.Id + "/CoverPicture/CoverPicture";
                }
            }


            var viewData = new
            {
                Id = subjectId,
                ProfilePicturePath = picturePath,
                Fullname = subjectFullname,
                PostType = "Text",
                FilePath = "",
                FileName = "",
                Description = "",
                Text = model.Content,
                PostId = newPost.Id,
                Created = newPost.Created,
                FileExtension = "",
                IsAdminPage = isAdminPage
            };

            var viewDictionary = viewData.ToViewDataDictionary();
            newPost.Content = ControlToString("~/Views/Post/PostOnWall.cshtml", viewDictionary);
            Repository.AddObject(newStatus);
            Repository.AddObject(newPost);

            //if currentUser is not the user that is posted on wall then we create extra post PostToFriend post);
            if (postedOnUser != null && model.BaseSubjectType == SubjectType.User && currentUser.Id != postedOnUser.Id)
            {

                // postToFriend post
                var newPost1 = new Post
                {
                    BaseObject = newStatus,
                    BaseSubject = currentUser,
                    Created = newStatus.Created,
                    Id = Guid.NewGuid(),
                    Type = BaseMessageType.Post,
                    Description = "PostToFriend status post",
                    Title = "PostToFriend status post",
                    PostType = PostType.Post,
                    CommentType = CommentType.PostWithoutComments
                };

                var viewData1 = new
                {
                    YourId = currentUser.Id,
                    ProfilePicturePath = profilePicturePath,
                    YourFullName = currentUser.FullName,
                    PostId = newPost.Id,
                    FriendFullname = postedOnUser.FullName,
                    FriendId = postedOnUser.Id,
                    Created = newPost.Created,
                    Filetype = "post"
                };

                var viewDictionary1 = viewData1.ToViewDataDictionary();
                newPost1.Content = ControlToString("~/Views/Post/PostToFriend.cshtml", viewDictionary1);
                Repository.AddObject(newPost1);

                // and we create one extra post that is special just for news feed// and it will look like user1 posted -> user2
                // postToFriend post for news feed only
                var newPost2 = new Post
                {
                    BaseObject = newStatus,
                    BaseSubject = postedOnUser,
                    Created = newStatus.Created,
                    Id = Guid.NewGuid(),
                    Type = BaseMessageType.Post,
                    Description = PostDescriptionType.PostOnWall + " status post - newsfeed", // it uses this in PostDelete function in PostController and in profileView for comments // DONT change
                    Title = PostDescriptionType.PostOnWall + " status post- newsfeed",
                    PostType = PostType.PostNewsFeed,
                    Parent = newPost,
                    CommentType = CommentType.PostWithItsComments,
                    Creator = currentUser
                };
                
                var viewData2 = new
                {
                    Id = currentUser.Id,
                    ProfilePicturePath = profilePicturePath,
                    Fullname = currentUser.FullName,
                    PostType = "Text",
                    FilePath = "",
                    FileName = "",
                    Description = "",
                    Text = model.Content,
                    PostId = newPost.Id,
                    Created = newPost.Created,
                    FileExtension = "",
                    FriendFullname = postedOnUser.FullName,
                    FriendId = postedOnUser.Id
                };

                var viewDictionary2 = viewData2.ToViewDataDictionary();
                newPost2.Content = ControlToString("~/Views/Post/PostOnWallNewsFeed.cshtml", viewDictionary2);
                Repository.AddObject(newPost2);

                //UserPostedOnYourWall notification
                var newNotification = new Notification()
                {
                    Active = true,
                    BaseSubject = postedOnUser,
                    Created = DateTime.Now,
                    Id = Guid.NewGuid(),
                    Type = BaseMessageType.Notification
                };
                var viewData3 = new
                {
                    UserId = currentUser.Id,
                    UserFullname = currentUser.FullName,
                    YourId = newPost.BaseSubject.Id,
                    PostId = newPost.Id
                };

                var viewDictionary3 = viewData3.ToViewDataDictionary();
                newNotification.Content = ControlToString("~/Views/Notification/UserPostedOnYourWall.cshtml", viewDictionary3);
                Repository.AddObject(newNotification);
            }
            
            //if group then we create PostOnGroupEventPage notification for every member
            if(model.BaseSubjectType == SubjectType.Group)
            {
                var group = Repository.AsQueryable<Group>().SingleOrDefault(gr => gr.Id == model.UserPostedOnId);
                var members = Repository.GetMembersOf(group.Id).Where(mem => mem.Id != currentUser.Id).ToList();
                var admin = Repository.GetAdminOf(group.Id);
                members.Add(admin);
                foreach (var member in members)
                {
                    var newNotification = new Notification()
                                          {
                                              Active = true,
                                              BaseSubject = member,
                                              Created = DateTime.Now,
                                              Id = Guid.NewGuid(),
                                              Type = BaseMessageType.Notification
                                          };
                    var viewData3 = new
                    {
                        UserPostedId = currentUser.Id,
                        UserPostedFullname = currentUser.FullName,
                        BaseSubjectType = "group",
                        SubjectId = group.Id,
                        SubjectFullname = group.FullName,
                        PostId = newPost.Id
                    };

                    var viewDictionary3 = viewData3.ToViewDataDictionary();
                    newNotification.Content = ControlToString("~/Views/Notification/PostOnGroupEventPage.cshtml", viewDictionary3);
                    Repository.AddObject(newNotification);
                }
                
            }

            Repository.SaveChanges();

            var newModel = new CommentPostModel()
                            {
                                Post = newPost,
                                ViewerProfilePicturePath = profilePicturePath
                            };

            return PartialView("Post", newModel);
        } 

        //
        // GET: /Status/Delete/5
        [Authorize]
        public ActionResult StatusDelete(Guid id)
        {
            var user = CurrentUser;
            var status = Repository.AsQueryable<Status>().SingleOrDefault(st => st.Id == id);
//            var allRemainingPosts = Repository.AsQueryable<Post>().Where(pst => pst.BaseObject.Id == status.Id);
//            foreach (var remainingPost in allRemainingPosts)
//            {
//                Repository.DeleteObject(remainingPost);
//            }
            Repository.DeleteObject(status);
            Repository.SaveChanges();
            
            return RedirectToAction("ProfileView", "Profile", new { id = user.Id });
        }

        #region Subject methods

        public override ActionResult ConfirmRelationshipNotification(Relationship relationship)
        {
            throw new NotImplementedException();
        }

        public override ActionResult PostponeRelationshipNotification(Relationship relationship)
        {
            throw new NotImplementedException();
        }

        public override ActionResult PostponeFailedRelationshipNotification(Relationship relationship)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Extra functions

        Dictionary<Status, Post> GetStatusAndPost(StatusCreateModel model)
        {
            var currentUser = CurrentUser;
            var newStatus = new Status();
            var newPost = new Post();
            //try to find what type is baseSubject))
            if (model.BaseSubjectType == SubjectType.Event)
            {
                var postedOnUser = Repository.AsQueryable<Event>().SingleOrDefault(ev => ev.Id == model.UserPostedOnId);
                newStatus = new Status()
                {
                    BaseSubject = currentUser,
                    Created = DateTime.Now,
                    Description = "Status",
                    Id = Guid.NewGuid(),
                    Name = "Status",
                    PrivacyType = model.Privacy,
                    Type = ObjectType.Status,
                    Content = model.Content
                };
                // PostOnWall post
                newPost = new Post
                {
                    BaseObject = newStatus,
                    BaseSubject = postedOnUser,
                    Created = newStatus.Created,
                    Id = Guid.NewGuid(),
                    Type = BaseMessageType.Post,
                    Description = PostDescriptionType.PostOnWall + " status post", // it uses this in PostDelete function in PostController and in profileView for comments // DONT change
                    Title = PostDescriptionType.PostOnWall + " status post",
                    PostType = PostType.Post,
                    CommentType = CommentType.PostWithItsComments,
                    Creator = currentUser
                };
            }
            else if (model.BaseSubjectType == SubjectType.Group)
            {
                var postedOnUser = Repository.AsQueryable<Group>().SingleOrDefault(ev => ev.Id == model.UserPostedOnId);
                newStatus = new Status()
                {
                    BaseSubject = currentUser,
                    Created = DateTime.Now,
                    Description = "Status",
                    Id = Guid.NewGuid(),
                    Name = "Status",
                    PrivacyType = model.Privacy,
                    Type = ObjectType.Status,
                    Content = model.Content
                };
                // PostOnWall post
                newPost = new Post
                {
                    BaseObject = newStatus,
                    BaseSubject = postedOnUser,
                    Created = newStatus.Created,
                    Id = Guid.NewGuid(),
                    Type = BaseMessageType.Post,
                    Description = PostDescriptionType.PostOnWall + " status post", // it uses this in PostDelete function in PostController and in profileView for comments // DONT change
                    Title = PostDescriptionType.PostOnWall + " status post",
                    PostType = PostType.Post,
                    CommentType = CommentType.PostWithItsComments,
                    Creator = currentUser
                };
            }
            else if (model.BaseSubjectType == SubjectType.Page)
            {
                var postedOnUser = Repository.AsQueryable<Page>().SingleOrDefault(ev => ev.Id == model.UserPostedOnId);
                newStatus = new Status()
                {
                    BaseSubject = currentUser,
                    Created = DateTime.Now,
                    Description = "Status",
                    Id = Guid.NewGuid(),
                    Name = "Status",
                    PrivacyType = model.Privacy,
                    Type = ObjectType.Status,
                    Content = model.Content
                };
                // PostOnWall post
                newPost = new Post
                {
                    BaseObject = newStatus,
                    BaseSubject = postedOnUser,
                    Created = newStatus.Created,
                    Id = Guid.NewGuid(),
                    Type = BaseMessageType.Post,
                    Description = PostDescriptionType.PostOnWall + " status post", // it uses this in PostDelete function in PostController and in profileView for comments // DONT change
                    Title = PostDescriptionType.PostOnWall + " status post",
                    PostType = PostType.Post,
                    CommentType = CommentType.PostWithItsComments,
                    Creator = currentUser
                };
            }
            else if (model.BaseSubjectType == SubjectType.User)
            {
                var postedOnUser = Repository.AsQueryable<User>().SingleOrDefault(ev => ev.Id == model.UserPostedOnId);
                newStatus = new Status()
                {
                    BaseSubject = currentUser,
                    Created = DateTime.Now,
                    Description = "Status",
                    Id = Guid.NewGuid(),
                    Name = "Status",
                    PrivacyType = model.Privacy,
                    Type = ObjectType.Status,
                    Content = model.Content
                };
                // PostOnWall post
                newPost = new Post
                {
                    BaseObject = newStatus,
                    BaseSubject = postedOnUser,
                    Created = newStatus.Created,
                    Id = Guid.NewGuid(),
                    Type = BaseMessageType.Post,
                    Description = PostDescriptionType.PostOnWall + " status post", // it uses this in PostDelete function in PostController and in profileView for comments // DONT change
                    Title = PostDescriptionType.PostOnWall + " status post",
                    PostType = PostType.Post,
                    CommentType = CommentType.PostWithItsComments,
                    Creator = currentUser
                };
            }

            var dictionary = new Dictionary<Status, Post>();
            dictionary.Add(newStatus, newPost);
            return dictionary;
        }

        #endregion
    }
}
